package cn.zhqr.core.interceptor;

import cn.zhqr.common.bean.response.ErrorCode;
import cn.zhqr.common.bean.response.OutResponse;
import cn.zhqr.common.util.str.StringUtils;
import cn.zhqr.common.utils.ServletKit;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.redis.Redis;

import java.util.List;

/**
 * 网站安全拦截器，防止机器频繁请求
 * Created by yantingjun on 2018/6/13.
 */
public class NetworkSecurityInterceptor implements Interceptor{
    private static final Log log = Log.getLog(NetworkSecurityInterceptor.class);

    private static final int monitor_time = PropKit.use("config.properties").getInt("security.monitor.time",5);
    private static final int monitor_limit = PropKit.use("config.properties").getInt("security.monitor.limit",100);
    private static final int monitor_locktime = PropKit.use("config.properties").getInt("security.monitor.locktime",3600);
    public static final List<String> white_ip_list = StringUtils.split(PropKit.use("config.properties").get("security.monitor.whitelist",""));
    @Override
    public void intercept(Invocation inv) {
        String ip = inv.getController().getRequest().getHeader("real-client-ip");
        if(StrKit.isBlank(ip)){
            ip = inv.getController().getPara("ip");
        }

        if(StrKit.isBlank(ip)){
            ip = ServletKit.getIp(inv.getController().getRequest());
        }

        if(StrKit.notBlank(ip) && !"127.0.0.1".equals(ip) && !white_ip_list.contains(ip)){
            Long count = Redis.use().incr("ip_count_"+ip);
            log.error("ip:"+ip+" path:"+inv.getController().getRequest().getRequestURI()+" 访问次数："+count);

            if(count==1){
                Redis.use().expire("ip_count_"+ip,monitor_time);
            }
            if(count == monitor_limit){
                Redis.use().expire("ip_count_" + ip,monitor_locktime);
                log.error(String.format("ip:%s %s秒内访问超过%s次,%s秒内禁止访问",ip,monitor_time,monitor_limit,monitor_locktime));
            }else if(count > monitor_limit){
                log.error(String.format("ip:%s %s秒内访问超过%s次,%s秒内禁止访问",ip,monitor_time,monitor_limit,monitor_locktime));
                inv.getController().renderJson(OutResponse.buildError(ErrorCode.OPERATE_TOO_FREQUENT));
                return;
            }
        }
        inv.invoke();
    }
}
